package com.activitiTest.test3;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.engine.ActivitiException;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;

/**
 * author : 冯孟活 ^_^ 
 * dates : 2015年9月1日 下午10:32:58 
 * class : 演示简单的公司请假流程
 * 
 * 		一个简单的流程分三个步骤：
 * 				1、发布流程(部署流程定义)
 * 				2、启动流程实例
 * 				3、完成任务(先查询任务，后完成任务)
 * 				4、挂起、激活一个流程实例(可选)
 */
public class VacationRequest {
	public static void main(String[] args) {

		/**
		 *  第一步：发布流程
		 */
		ProcessEngine processEngine = ProcessEngineConfiguration // 通过流程引擎配置类来创建流程引擎
				.createProcessEngineConfigurationFromResource("activiti.cfg.xml").buildProcessEngine();
		RepositoryService repositoryService = processEngine.getRepositoryService(); // 通过流程引擎来得到知识库服务
		repositoryService.createDeployment().addClasspathResource("VacationRequest.bpmn").deploy(); // 通过只是库部署流程定义
		System.out.println("流程定义的个数="+repositoryService.createDeploymentQuery().count()); // 查询所有发布的流程定义的个数
		
		/**
		 *  第二步：启动一个流程实例
		 */
		/*定义Map来存放流程变量：流程变量经常会被用到，因为他们赋予来自同一个流程定义的不同流程实例
		   的特别含义，简单来说，流程变量是区分流程实例的关键
		*/
		Map<String, Object> variables = new HashMap<>(); // 定义一个Map来存放流程变量
		variables.put("employeeName","Kermit");
		variables.put("numberOfDays",new Integer(4));
		variables.put("vacationMotivation","I'm really tired!");
		RuntimeService runtimeService = processEngine.getRuntimeService(); // 获取运行服务
		runtimeService.startProcessInstanceByKey("vacationRequest",variables); // 通过运行服务来启动流程实例，并且设置流程变量(通过key 或者 id 部署都可以)
		System.out.println("流程实例的个数="+runtimeService.createProcessInstanceQuery().count()); // 通过运行服务来查询所有的流程实例的个数
		
		/**
		 *  第三部：完成任务
		 */
		TaskService taskService = processEngine.getTaskService(); // 通过流程引擎获取任务服务
		List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("management").list(); // 通过任务服务来查询任务候选组(这是通过组来分区)
		for (Task task : tasks) { // 遍历打印任务
			System.err.println("能找到的任务="+task.getName());
		}
		Task task = tasks.get(0); // 获取第一个任务
		Map<String,Object> taskVariables = new HashMap<>(); // 定义一个Map来存放任务变量
		taskVariables.put("vacationApproved","false");
		taskVariables.put("managerMotivation","We have a tight deadline!");
		taskService.complete(task.getId(),taskVariables); // 根据Id来完成任务
		
		/**
		 *  挂起，激活一个流程
		 */
		/*
		 * 我们可以挂起一个流程定义。当挂起流程定义时， 就不能创建新流程了（会抛出一个异常）。 
		 * 可以通过RepositoryService挂起一个流程：
		 */
		//repositoryService.suspendProcessDefinitionByKey("vacationRequest"); // 挂起一个流程定义
		//try{
			//runtimeService.startProcessInstanceByKey("vacationRequest"); // 启动一个流程实例
		//}catch(ActivitiException e){ // 这里会抛出一个Activiti自定义异常
			//e.printStackTrace();
		//}
		
		/*
		 * 备注下：
		 * 		也可以挂起一个流程实例。挂起时，流程不能继续执行（比如，完成任务会抛出异常），
		 * 异步操作（比如定时器）也不会执行。 挂起流程实例可以调用 runtimeService.suspendProcessInstance方法。 
		 * 激活流程实例可以调用runtimeService.activateProcessInstanceXXX方法。
		 */
	}
}
